/**
 * @Author: jichang
 * @Date: 2024/10/29 14:43:09
 * @LastEditors: jichang
 * @LastEditTime: 2024/10/29 14:43:09
 * Description: TemplateDispatcher
 */
#pragma once
namespace messaging {
template<typename PreviousDispatcher, typename Msg, typename Func>
    class TemplateDispatcher {
    public:
        TemplateDispatcher(TemplateDispatcher&& other):
            q(other.q), prev(other.prev), f(std::move(other.f)), chained(other.chained) {
            other.chained = true;
        }
        TemplateDispatcher(queue* q_, PreviousDispatcher* prev_, Func&& f_):
            q(q_), prev(prev_), f(std::forward<Func>(f_)), chained(false) {
            prev_->chained = true;
        }
        // 可以链接其他处理器
        template<typename OtherMsg, typename OtherFunc>
        TemplateDispatcher<TemplateDispatcher, OtherMsg, OtherFunc>
        handle(OtherFunc&& of) {
            return TemplateDispatcher
                <TemplateDispatcher, OtherMsg, OtherFunc>
                (q, this, std::forward<OtherFunc>(of));
        }
        ~TemplateDispatcher() noexcept(false) {
            if (!chained) {
                wait_and_dispatch();
            }
        }
    private:
        queue* q;
        PreviousDispatcher* prev;
        Func f;
        bool chained;

        TemplateDispatcher(TemplateDispatcher const&) = delete;
        TemplateDispatcher& operator=(TemplateDispatcher const&) = delete;

        // 所有特化的该类型实例都是友元
        template<typename Dispatcher, typename OtherMsg, typename OtherFunc>
        friend class TemplateDispatcher;

        // 如果不抛出异常，就需要检查消息是否已经得到了处理
        void wait_and_dispatch() {
            while(1) {
                auto msg = q->wait_pop();
                if (dispatch(msg)) {
                    break;
                }
            }
        }
        bool dispatch(std::shared_ptr<message_base> const& msg) {
            // 判断消息是否匹配，书本山是赋值，这里难道不是判等吗？
            if (wrapped_message<Msg>* wrapper = dynamic_cast<wrapped_message<Msg>*>(msg.get())) {
                f(wrapper->contents);
                return true;
            } else {
                // 链接到之前的调度器
                return prev->dispatch(msg);
            }
        }
    };
}   
